import { Command } from "commander";
import { template as t } from "@ibizlab/template";
import * as rm from "rimraf";
import { normalize, resolve } from "path";
import * as fs from "fs";
import { ICommand } from "../../../interface";
import cpFile from "cp-file";
import { glob } from "glob";
import chalk from "chalk";
import { skipOverWrite, winToUnixPath } from "../../../util";
import { installHelpers } from "../../../helpers";
import pkg from '../../../../package.json';
import { logger } from "@ibizlab/template-core";

/**
 * 命令输入参数
 *
 * @export
 * @interface TemplateGenerateCommandOptions
 */
export interface TemplateGenerateCommandOptions {
  /**
   * 模型目录
   *
   * @type {string}
   */
  model: string;
  /**
   * 模板目录
   *
   * @type {string}
   */
  template: string;
  /**
   * 模板输出目录
   *
   * @type {string}
   */
  output: string;
  /**
   * 指定发布的应用
   *
   * @type {boolean}
   */
  app: string;
  /**
   * 是否开发模式启动
   *
   * @type {boolean}
   */
  dev: boolean;
  /**
   * 清理输出目录
   *
   * @type {boolean}
   */
  clean: boolean;

  /**
   * 是否全覆盖
   *
   * @type {boolean}
   */
  all: boolean;
}

/**
 * 运行模板编译
 *
 * @export
 * @class TemplateGenerateCommand
 * @implements {ICommand}
 */
export class TemplateGenerateCommand implements ICommand {
  load(program: Command): void {
    program
      .command("generate")
      .description("编译模板并运行")
      .option("-m, --model <model-path>", "模型目录")
      .option("-t, --template <template-path>", "模板目录")
      .option("-o, --output <output-path>", "输出目录, 默认输出: 模板目录/out")
      .option("--app [app-code-name]", "发布模式改为应用, 模型目录将识别为应用")
      .option("--dev", "开发模式启动")
      .option("--clean", "清理输出目录")
      .option("--all", "是否全覆盖")
      .action(this.action.bind(this));
  }

  /**
   * 执行行为
   *
   * @param {TemplateGenerateCommandOptions} options
   * @return {*}  {Promise<void>}
   * @memberof TemplateGenerateCommand
   */
  async action(options: TemplateGenerateCommandOptions): Promise<void> {
    const { model, template, output, app, dev, clean, all } = options;
    const modelFolder = normalize(resolve(model));
    const {name} = pkg;
    const baseTempFolder = normalize(
      resolve(`./node_modules/${name}/template`)
    );
    const baseAssertFolder = normalize(
      resolve(`./node_modules/${name}/asset`)
    );
    const tempTempFolder = normalize(
      resolve(
        `./node_modules/${name}/template-${new Date().getTime()}`
      )
    );
    const outputFolder = normalize(resolve(output));
    if (clean === true) {
      rm.sync(`${outputFolder}/*`);
    }
    console.log(`${chalk.green("Start Copy Template ......")} \n`);
    // 创建临时目录
    fs.mkdirSync(tempTempFolder);
    if (!all) {
      // 基础模板
      const targetBaseTempFolder = winToUnixPath(baseTempFolder);
      const targetTempTempFolder = winToUnixPath(tempTempFolder);
      const basePaths = glob.sync(`${targetBaseTempFolder}/**`, {
        nodir: true,
        dot: true,
      });
      await Promise.all(
        basePaths.map((pathStr) => {
          const outFilePathStr =
            targetTempTempFolder + pathStr.replace(targetBaseTempFolder, "");
          return cpFile(pathStr, outFilePathStr);
        })
      );
    }
    if (template) {
      const extendTempFolder = normalize(resolve(template));
      const targetTempTempFolder = winToUnixPath(tempTempFolder);
      const targetExtendTempFolder = winToUnixPath(extendTempFolder);
      const extendPaths = glob.sync(`${targetExtendTempFolder}/**`, {
        nodir: true,
        dot: true,
      });
      await Promise.all(
        extendPaths.map((pathStr) => {
          const outFilePathStr =
            targetTempTempFolder + pathStr.replace(targetExtendTempFolder, "");
          return cpFile(pathStr, outFilePathStr);
        })
      );
    }
    console.log(`${chalk.green("Completed Copy Template ......")} \n`);
    console.log(`${chalk.green("Start Generate Template File ......")} \n`);
    t.init({
      modelFolder,
      tempFolder: tempTempFolder,
      outFolder: outputFolder,
      mode: app ? "app" : "sys",
      app,
      dev,
    });
    installHelpers(t);
    await t.run();
    const stat = fs.statSync(tempTempFolder);
    if (stat.isDirectory()) {
      rm.sync(`${tempTempFolder}`);
    }
    console.log(`${chalk.green("Completed Generate Template File ......")} \n`);
    console.log(`${chalk.green("Start Copy Assert File ......")} \n`);
    const baseAssertTempFolder = winToUnixPath(baseAssertFolder);
    const assertPaths = glob.sync(`${baseAssertTempFolder}/**`, {
      nodir: true,
      dot: true,
    });
    await Promise.all(
      assertPaths.map(async (pathStr) => {
        const outFilePathStr = outputFolder + pathStr.replace(baseAssertTempFolder, "");
        const result = await skipOverWrite(outFilePathStr);
        if(!result){
          logger.info('拷贝文件', `${pathStr.replace(baseAssertTempFolder, "")}`);
          return cpFile(pathStr, outFilePathStr);
        }
      })
    );
    console.log(`${chalk.green("Completed Copy Assert File ......")} \n`);
    process.exit();
  }
}
